#include "cView.h"
#include "cGame.h"
#include "stdio.h"
#include "VideoDriver.h"
CView* CView::s_pInstance = 0;
LRESULT WINAPI ESWindowProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
{
	return CView::GetInstance()->WndProc(hWnd, uMsg, wParam, lParam);
}
LRESULT WINAPI CView::WndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
{
	LRESULT  lRet = 1; 

	switch (uMsg) 
	{ 
	case WM_CREATE:
		break;

	case WM_PAINT:
		{
			m_esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			if ( m_esContext && m_esContext->drawFunc )
				m_esContext->drawFunc ( m_esContext );

			ValidateRect( m_esContext->hWnd, NULL );
		}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);             
		break; 

	case WM_KEYDOWN:
		{
			// POINT      point;
			// ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			// GetCursorPos( &point );

			// if ( esContext && esContext->keyDownFunc )
				// esContext->keyDownFunc ( esContext, (unsigned char) wParam, 
				// (int) point.x, (int) point.y );
		}
		break;
	case WM_KEYUP:
		{
			// POINT      point;
			// ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			// GetCursorPos( &point );

			// if ( esContext && esContext->keyUpFunc )
				// esContext->keyUpFunc ( esContext, (unsigned char) wParam, 
				// (int) point.x, (int) point.y );
		}
		break;
	case WM_LBUTTONDOWN:
		{			
			// POINTS      point;
			// ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			// point = MAKEPOINTS(lParam);
			// if ( esContext && esContext->mouseDownFunc )
				// esContext->mouseDownFunc ( esContext, (int) point.x, (int) point.y );
		}
		break;
	case WM_MOUSEMOVE:
		// if (wParam & MK_LBUTTON)
		// {
			// POINTS      point;
			// ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			// point = MAKEPOINTS(lParam);
			// if ( esContext && esContext->mouseMoveFunc )
				// esContext->mouseMoveFunc ( esContext, (int) point.x, (int) point.y );
		// }
		break;
	case WM_LBUTTONUP:
		// {
			// POINTS     point;
			// ESContext *esContext = (ESContext*)(LONG_PTR) GetWindowLongPtr ( hWnd, GWL_USERDATA );

			// point = MAKEPOINTS(lParam);

			// if ( esContext && esContext->mouseUpFunc )
				// esContext->mouseUpFunc ( esContext, (int) point.x, (int) point.y );
		// }
		break;
	default: 
		lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); 
		break; 
	} 

	return lRet; 
}

//////////////////////////////////////////////////////////////////
//
//  Public Functions
//
//

///
//  WinCreate()
//
//      Create Win32 instance and window
//
void GameUpdate ( ESContext *esContext, float deltaTime )
{
	
	printf("..... Update\n");
}
void PaintObject()
{
	// Limit FPS
	DWORD start, end;
	start = GetTickCount();

	// Render something here
	VideoDriver::GetInstance()->DrawCircle(100.0f, 100.0f, 100.0f);
	VideoDriver::GetInstance()->FillRect(0, 0, 100, 100);

	// Limit FPS
	end = GetTickCount();
	DWORD deltaTime = end - start;
	if (deltaTime < 1000.0/LIMIT_FPS)
		Sleep(1000/LIMIT_FPS - deltaTime);
}
void GameDraw ( ESContext *esContext )
{
	PaintObject();
	eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
	// CView::GetInstance()->Render();
	// CView::GetInstance()->RefreshGL();
	printf("..... Paint\n");
}
void CView::RefreshGL()
{
	eglSwapBuffers ( m_esContext->eglDisplay, m_esContext->eglSurface );
}
void CView::Render()
{
	// Limit FPS
	DWORD start, end;
	start = GetTickCount();

	// Render something here
	VideoDriver::GetInstance()->DrawCircle(100.0f, 100.0f, 100.0f);
	VideoDriver::GetInstance()->FillRect(0, 0, 100, 100);

	// Limit FPS
	end = GetTickCount();
	DWORD deltaTime = end - start;
	if (deltaTime < 1000.0/LIMIT_FPS)
		Sleep(1000/LIMIT_FPS - deltaTime);
}
GLboolean CView::WinCreate (const char* title, int width, int height)
{
	esInitContext ( m_esContext);
	m_esContext->width = width;
	m_esContext->height = height;
	esRegisterDrawFunc(m_esContext, GameDraw );
	esRegisterUpdateFunc(m_esContext, GameUpdate);
	WNDCLASS wndclass = {0}; 
	DWORD    wStyle   = 0;
	RECT     windowRect;
	HINSTANCE hInstance = GetModuleHandle(NULL);


	wndclass.style         = CS_OWNDC;
	wndclass.lpfnWndProc   = (WNDPROC)ESWindowProc; 
	wndclass.hInstance     = hInstance; 
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 
	wndclass.lpszClassName = "opengles2.0"; 

	if (!RegisterClass (&wndclass) ) 
		return FALSE; 

	wStyle = WS_VISIBLE | WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION;

	// Adjust the window rectangle so that the client area has
	// the correct number of pixels
	windowRect.left = 0;
	windowRect.top = 0;
	windowRect.right = m_esContext->width;
	windowRect.bottom = m_esContext->height;

	AdjustWindowRect ( &windowRect, wStyle, FALSE );



	m_esContext->hWnd = CreateWindow(
		"opengles2.0",
		title,
		wStyle,
		0,
		0,
		windowRect.right - windowRect.left,
		windowRect.bottom - windowRect.top,
		NULL,
		NULL,
		hInstance,
		NULL);

	// Set the m_esContext* to the GWL_USERDATA so that it is available to the 
	// ESWindowProc
	SetWindowLongPtr (  m_esContext->hWnd, GWL_USERDATA, (LONG) (LONG_PTR) m_esContext );


	// if ( m_esContext->hWnd == NULL )
		// return GL_FALSE;

	ShowWindow ( m_esContext->hWnd, TRUE );

	return GL_TRUE;
}

///
//  winLoop()
//
//      Start main windows loop
//
void CView::WinLoop ()
{
	MSG msg = { 0 };
	int done = 0;
	DWORD lastTime = GetTickCount();

	while (!done)
	{
		int gotMsg = (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0);
		DWORD curTime = GetTickCount();
		float deltaTime = (float)( curTime - lastTime ) / 1000.0f;
		lastTime = curTime;

		if ( gotMsg )
		{
			if (msg.message==WM_QUIT)
			{
				done=1; 
			}
			else
			{
				TranslateMessage(&msg); 
				DispatchMessage(&msg); 
			}
		}
		else
			SendMessage( m_esContext->hWnd, WM_PAINT, 0, 0 );

		// Call update function if registered
		if ( m_esContext->updateFunc != NULL )
			m_esContext->updateFunc ( m_esContext, deltaTime );
	}
}